package dk.itu.spvc.tourtracker.model;

import java.util.ArrayList;
import java.util.Arrays;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.text.method.DigitsKeyListener;
import android.util.Log;

import com.skyhookwireless.wps.IPLocationCallback;
import com.skyhookwireless.wps.WPSAuthentication;
import com.skyhookwireless.wps.WPSLocationCallback;
import com.skyhookwireless.wps.WPSPeriodicLocationCallback;
import com.skyhookwireless.wps.WPSStreetAddressLookup;
import com.skyhookwireless.wps.XPS;

public class Wps implements OnSharedPreferenceChangeListener
{
	
	// PRIVATE FIELDS ---------------------------------------------------------
	
	// Debug
	private static final String TAG = "TourTracker";
	private static final boolean D = true;
	
	private static final String SERVER_URL_KEY = "Server URL";

    private String _username = null; 
    private String _realm = null;    
    private String _localFilePath = null;
    private long _period;
    private int _iterations;
    private int _desiredXpsAccuracy;
    private String _tilingPath = null;
    private long _maxDataSizePerSession;
    private long _maxDataSizeTotal;
    private String _serverUrl;
    private WPSStreetAddressLookup _streetAddressLookup;
    private XPS _xps;

    
    // CTOR -------------------------------------------------------------------
    
    public Wps(Context context)
    {
    	// Create the XPS instance, passing in our Context
        _xps = new XPS(context);

        if(D) Log.d(TAG, "Wps - Started");
        
        // Listen for settings changes
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        preferences.registerOnSharedPreferenceChangeListener(this);
        
        // Read existing preferences
        onSharedPreferenceChanged(preferences, "Username");
        onSharedPreferenceChanged(preferences, "Realm");
        onSharedPreferenceChanged(preferences, "Local File Path");
        onSharedPreferenceChanged(preferences, "Period");
        onSharedPreferenceChanged(preferences, "Iterations");
        onSharedPreferenceChanged(preferences, "Desired XPS Accuracy");
        onSharedPreferenceChanged(preferences, "Street Address Lookup");
        onSharedPreferenceChanged(preferences, "Tiling Path");
        onSharedPreferenceChanged(preferences, "Max Data Per Session");
        onSharedPreferenceChanged(preferences, "Max Data Total");

        // TODO: Hardcoded settings
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString("Username", "alvioshki");
        editor.putString("Realm", "ITU");
        editor.commit();
        
    }

    
    // PUBLIC METHODS ---------------------------------------------------------

    public void getIPLocation(IPLocationCallback callback) {
    	WPSAuthentication auth = new WPSAuthentication(_username, _realm);
        _xps.getIPLocation(auth, _streetAddressLookup, callback);
    }

    public void getWPSLocation(WPSLocationCallback callback) {
    	WPSAuthentication auth = new WPSAuthentication(_username, _realm);
        _xps.getLocation(auth, _streetAddressLookup, callback);
    }
    
    public void getWPSPeriodicLocation(WPSPeriodicLocationCallback callback) {
    	WPSAuthentication auth = new WPSAuthentication(_username, _realm);
        _xps.getPeriodicLocation(auth, _streetAddressLookup, _period, _iterations, callback);
    }
    
    public void getXPSLocation(WPSPeriodicLocationCallback callback) {
    	WPSAuthentication auth = new WPSAuthentication(_username, _realm);
        _xps.getXPSLocation(auth,
        		// note we convert _period to seconds
        		(int) (_period / 1000),
        		_desiredXpsAccuracy,
        		callback);
    }
    
    public void abort () {
    	_xps.abort();
    }

    /**
     * Preferences management code
     */
    public static class Preferences
        extends PreferenceActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setPreferenceScreen(createRootPreferenceScreen());
        }

        private PreferenceScreen createRootPreferenceScreen()
        {
            final PreferenceScreen root =
                getPreferenceManager().createPreferenceScreen(this);

            final PreferenceCategory category = new PreferenceCategory(this);
            category.setTitle("WpsApiTest Settings");
            root.addPreference(category);

            for (int i = 0; i < options.length;)
            {
                int iIncrement;
                Option optionType = (Option) options[i + 1];
                Preference setting = null;
                if (optionType == Option.TEXT
                        || optionType == Option.NONNEGATIVE_INTEGER)
                {
                    final EditTextPreference textSetting =
                        new EditTextPreference(this);
                    setting = textSetting;
                    textSetting.getEditText().setSingleLine();
                    if (optionType == Option.NONNEGATIVE_INTEGER)
                        textSetting.getEditText()
                                   .setKeyListener(new DigitsKeyListener(false,
                                                                         false));
                    iIncrement = 2;
                }
                else if (optionType == Option.CHECKBOX)
                {
                    final CheckBoxPreference checkSetting =
                        new CheckBoxPreference(this);
                    setting = checkSetting;
                    iIncrement = 2;
                }
                else if (optionType == Option.LIST)
                {
                    final ListPreference listSetting = new ListPreference(this);
                    setting = listSetting;
                    listSetting.setEntries((String[]) options[i+2]);
                    listSetting.setEntryValues((String[]) options[i+2]);
                    iIncrement = 3;
                }
                else
                {
                    iIncrement = 2;
                }
                if (setting != null)
                {
                    setting.setKey((String) options[i]);
                    setting.setTitle((String) options[i]);
                    category.addPreference(setting);
                }
                i += iIncrement;
            }

            return root;
        }

        private enum Option
        {
            TEXT,
            NONNEGATIVE_INTEGER,
            LIST,
            CHECKBOX;
        }

        private static Object[] options =
            new Object[]
                {"Username"             , Option.TEXT,
                 "Realm"                , Option.TEXT,
                 SERVER_URL_KEY         , Option.TEXT,
                 "Local File Path"      , Option.TEXT,
                 "Period"               , Option.NONNEGATIVE_INTEGER,
                 "Iterations"           , Option.NONNEGATIVE_INTEGER,
                 "Desired XPS Accuracy" , Option.NONNEGATIVE_INTEGER,
                 "Tiling Path"          , Option.TEXT,
                 "Max Data Per Session" , Option.NONNEGATIVE_INTEGER,
                 "Max Data Total"       , Option.NONNEGATIVE_INTEGER,
                 "Street Address Lookup", Option.LIST, new String[] {"None", "Limited", "Full"}};

    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                                          String key)
    {
        if (sharedPreferences.getString(key, "default").equals(""))
        {
            // delete empty preferences so we get the default values below
            final Editor editor = sharedPreferences.edit();
            editor.remove(key);
            editor.commit();
        }

        if (key.equals("Username"))
            _username = sharedPreferences.getString("Username", "");
        else if (key.equals("Realm"))
            _realm = sharedPreferences.getString("Realm", "");
        else if (key.equals("Local File Path"))
        {
            _localFilePath = sharedPreferences.getString("Local File Path", "");
            // TODO: clean this up?
            ArrayList<String> paths = null;
            if (! _localFilePath.equals(""))
            {
                paths = new ArrayList<String>(Arrays.asList(new String[]{_localFilePath}));
            }
            _xps.setLocalFilePaths(paths);
        }
        else if (key.equals("Period"))
        {
            _period =
                Long.valueOf(sharedPreferences.getString("Period", "5000"));
        }
        else if (key.equals("Iterations"))
        {
            _iterations =
                Integer.valueOf(sharedPreferences.getString("Iterations", "1"));
        }
        else if (key.equals("Desired XPS Accuracy"))
        {
            _desiredXpsAccuracy = Integer.valueOf(sharedPreferences.getString("Desired XPS Accuracy", "30"));
        }
        else if (key.equals("Tiling Path"))
        {
            _tilingPath = sharedPreferences.getString("Tiling Path", "");
        }
        else if (key.equals("Max Data Per Session"))
        {
            _maxDataSizePerSession =
                Long.valueOf(sharedPreferences.getString("Max Data Per Session", "0"));
        }
        else if (key.equals("Max Data Total"))
        {
            _maxDataSizeTotal =
                Long.valueOf(sharedPreferences.getString("Max Data Total", "0"));
        }
        else if (key.equals("Street Address Lookup"))
        {
            String setting = sharedPreferences.getString("Street Address Lookup", "None");
            if (setting.equals("None"))
            {
                _streetAddressLookup = WPSStreetAddressLookup.WPS_NO_STREET_ADDRESS_LOOKUP;
            }
            else if (setting.equals("Limited"))
            {
                _streetAddressLookup = WPSStreetAddressLookup.WPS_LIMITED_STREET_ADDRESS_LOOKUP;
            }
            else if (setting.equals("Full"))
            {
                _streetAddressLookup = WPSStreetAddressLookup.WPS_FULL_STREET_ADDRESS_LOOKUP;
            }
        }
        else if (key.equals(SERVER_URL_KEY))
        {
            _serverUrl = sharedPreferences.getString(SERVER_URL_KEY, "");
            XPS.setServerUrl(_serverUrl);
        }
        
        _xps.setTiling(_tilingPath,
                       _maxDataSizePerSession,
                       _maxDataSizeTotal,
                       null);
    }
    
}
